package com.example.klinedemo

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PorterDuff
import com.example.klinedemo.bean.KLineItem
import com.example.klinedemo.utils.DensityUtils
import kotlin.math.abs

class KLineViewBitMapUtil(val view: KLineView) {

    companion object {
        const val DEFAULT_SHOW_K_LINE_COUNT = 60
    }


    private val densityUtils = DensityUtils(view.context)

    // 每k线的左右外边距
    private val kLinePadding = densityUtils.dpToPx(1f)

    // 缓冲层 Bitmap
    private var bufferBitmap: Bitmap? = null

    // 缓冲层 Canvas
    private var bufferCanvas: Canvas? = null

    private val paint = Paint()

    // 绿色
    private val colorGreen = Color.parseColor("#66CC99")

    // 红色
    private val colorRed = Color.parseColor("#FF6666")

    // 黑色
    private val colorBlack = Color.parseColor("#1A1A1A")

    // 灰色
    private val colorGrey = Color.parseColor("#CCCCCC")

    // data数据
    private val klineData: ArrayList<KLineItem> = arrayListOf()

    // 屏幕左上角max的价格
    private var frameMaxValue = 0.0

    // 屏幕左下角min的价格
    private var frameMinValue = 0.0

    // 整个view 边框上下左右的边距
    private val framePadding = densityUtils.dpToPx(3f)

    // 每根k线的宽度 包含k线的边距
    public val kLineWidth: Float by lazy {
        ((view.width - framePadding * 2) / DEFAULT_SHOW_K_LINE_COUNT)
    }


    // view主图 减去边距和底部时间文字的高度
    private val viewBottom: Float by lazy {
        view.height - framePadding
    }

    // view主图 减去边距的宽度
    private val viewLeft: Float by lazy {
        view.width - framePadding
    }

    // view主图下方数据文字的高度
    private var viewBottomDateHeight = 0.0f

    public fun recycle() {
        bufferBitmap?.recycle()
    }

    fun initBitMap(w: Int, h: Int) {
        // 创建新缓冲层（ARGB_8888 格式支持透明通道）
        bufferBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565)

        bufferCanvas = bufferBitmap?.let {
            Canvas(it)
        }
        bufferCanvas?.drawColor(Color.WHITE)

    }

    fun onDraw(canvas: Canvas) {
        // 优先使用缓冲层渲染
        bufferBitmap?.let {
            canvas.save()
            canvas.drawBitmap(it, 0f, 0f, null)
            canvas.restore()
        }
    }

    /**
     * 绘制的开始
     */
    fun drawLine(klineData: MutableList<KLineItem>) {
        // 截取当前数组需要展示的数组
//        if (this.klineData.containsAll(klineData)) {
//            return
//        }
        handleData(klineData)
        // 清空上一帧内容
        bufferCanvas?.drawColor(Color.WHITE)

        // 绘制底部的时间
        drawBottomDate()
        // 画K线的边框
        drawFrame()
        // 画价格区分线
        drawPriceLine()
        // 画边框的最大最小值
        drawFrameMaxMinValue()
        // 开始绘制k线
        drawKLine(framePadding, 0)
    }

    /**
     * 绘制底部的时间
     */
    private fun drawBottomDate() {
        // 1. 更改画笔
        paint.color = colorBlack
        paint.textSize = densityUtils.dpToPx(10.0f)
        paint.isAntiAlias = true; // 设置抗锯齿，使文字边缘更平滑

        val kLineMinDate = klineData[0].date
        val kLineMaxDate = klineData[kLineMinDate.length - 1].date
        val kLineMidDate = klineData[kLineMinDate.length / 2].date

        // 最小值
        bufferCanvas?.drawText(
            kLineMinDate,
            framePadding * 2,
            view.height.toFloat() - framePadding - framePadding,
            paint
        )

        var measureText = paint.measureText(kLineMidDate)
        // 中间值
        bufferCanvas?.drawText(
            kLineMidDate,
            viewLeft / 2 - measureText / 2,
            view.height.toFloat() - framePadding - framePadding,
            paint
        )

        // 最大值
        measureText = paint.measureText(kLineMaxDate)
        bufferCanvas?.drawText(
            kLineMaxDate,
            viewLeft - measureText,
            view.height.toFloat() - framePadding - framePadding,
            paint
        )
        // 获取主图底部字体高度
        val fontMetrics = paint.fontMetrics
        viewBottomDateHeight = fontMetrics.descent - fontMetrics.ascent
    }


    /**
     * 画k线
     */
    private fun drawKLine(currX: Float, index: Int) {
        if (index >= klineData.size - 1) return
        val kLineItem = klineData[index]
        // 每元代表
        val maxPrice = frameMaxValue * 100
        val minPrice = frameMinValue * 100
        val openPrice = kLineItem.open * 100
        val closePrice = kLineItem.close * 100
        val highPrice = kLineItem.high * 100
        val lowPrice = kLineItem.low * 100

        val pxPrice = viewBottom / (maxPrice - minPrice)
        // 当前item 开盘价的y坐标
        val openY = (openPrice - minPrice) * pxPrice
        // 闭盘价
        val closeY = (closePrice - minPrice) * pxPrice
        // 最高价
        val highY = (highPrice - minPrice) * pxPrice
        // 最低价
        val lowY = (lowPrice - minPrice) * pxPrice
        paint.color = getPaintColor(kLineItem)
        paint.style = Paint.Style.FILL

        // K线的坐标 主要记录X坐标
        val kLineLeftX = currX + kLinePadding
        val kLineRightX = currX + kLineWidth

        // 画k线实体
        bufferCanvas?.drawRect(
            kLineLeftX, openY.toFloat(),
            kLineRightX, closeY.toFloat(),
            paint
        )

        kLineItem.kLineX = kLineLeftX;
        kLineItem.kLineY = openY.toFloat()

        // 画上影线
        bufferCanvas?.drawLine(
            (kLineLeftX + kLineRightX) / 2.0f,
            highY.toFloat(), (kLineLeftX + kLineRightX) / 2.0f, openY.toFloat(), paint
        )
        // 画上影线
        bufferCanvas?.drawLine(
            (kLineLeftX + kLineRightX) / 2.0f,
            closeY.toFloat(), (kLineLeftX + kLineRightX) / 2.0f, lowY.toFloat(), paint
        )

        drawKLine(kLineRightX, index + 1)
    }

    /**
     * 画价格区分线
     */
    private fun drawPriceLine() {
        paint.apply {
            isAntiAlias = true       // 关闭抗锯齿（避免线条模糊）
            strokeWidth = 1.5f         // 设置线宽为 1px
            style = Paint.Style.STROKE // 笔触样式为描边
            color = colorGrey       // 线条颜色
        }

        bufferCanvas?.drawLine(
            framePadding,
            viewBottom / 3,
            viewLeft,
            viewBottom / 3,
            paint
        )

        bufferCanvas?.drawLine(
            framePadding,
            viewBottom / 1.5f,
            viewLeft,
            viewBottom / 1.5f,
            paint
        )


    }

    /**
     * 画k线的边框
     */
    private fun drawFrame() {
        paint.apply {
            isAntiAlias = true       // 关闭抗锯齿（避免线条模糊）
            strokeWidth = 1.5f         // 设置线宽为 1px
            style = Paint.Style.STROKE // 笔触样式为描边
            color = colorGrey       // 线条颜色
        }

        bufferCanvas?.drawLine(
            framePadding,
            framePadding,
            view.width - framePadding,
            framePadding,
            paint
        )
        bufferCanvas?.drawLine(
            framePadding,
            framePadding,
            framePadding,
            view.height - framePadding,
            paint
        )
        bufferCanvas?.drawLine(
            framePadding,
            view.height - framePadding,
            view.width - framePadding,
            view.height - framePadding,
            paint
        )

        bufferCanvas?.drawLine(
            view.width - framePadding,
            framePadding,
            view.width - framePadding,
            view.height - framePadding,
            paint
        )

        // 底部时间上方的框线
        bufferCanvas?.drawLine(
            framePadding,
            viewBottom - viewBottomDateHeight - 5f,
            viewLeft,
            viewBottom - viewBottomDateHeight - 5f,
            paint
        )

    }

    private fun handleData(klineData: MutableList<KLineItem>) {

        this.klineData.clear()
        this.klineData.addAll(klineData)
        frameMaxValue = klineData.maxOfOrNull { it.high } ?: 0.0
        frameMinValue = klineData.minOfOrNull { it.low } ?: 0.0
    }


    /**
     * 画边框的最大值最小值
     */
    private fun drawFrameMaxMinValue() {
        // 1. 更改画笔
        paint.color = colorBlack
        paint.style = Paint.Style.FILL // 笔触样式为描边
        paint.textSize = densityUtils.dpToPx(12.0f)
        paint.isAntiAlias = true; // 设置抗锯齿，使文字边缘更平滑
        // 最大值
        bufferCanvas?.drawText(
            frameMaxValue.toString(),
            framePadding + framePadding,
            paint.textSize + framePadding,
            paint
        );
        // 最小值
        bufferCanvas?.drawText(
            frameMinValue.toString(),
            framePadding + framePadding,
            viewBottom - viewBottomDateHeight - 15f,
            paint
        );
    }


    /**
     * 根据价格获取画笔的颜色
     */
    private fun getPaintColor(kLineItem: KLineItem): Int {
        return if (kLineItem.open > kLineItem.close) {
            colorGreen
        } else if (kLineItem.open < kLineItem.close) {
            colorRed
        } else {
            colorGreen
        }
    }

    fun drawCrosshairs(x: Float, y: Float) {
        if (x == 0f) return
        if (y == 0f) return

        paint.apply {
            isAntiAlias = true       // 关闭抗锯齿（避免线条模糊）
            strokeWidth = densityUtils.dpToPx(1f)         // 设置线宽为 1px
            color = colorGrey       // 线条颜色
        }

        val selectItem = klineData.first { // 当前选中的k线
            it.kLineX > x && abs(it.kLineX % x) <= kLineWidth
        }

        bufferCanvas?.drawLine(
            framePadding, y,
            view.width - framePadding,
            y,
            paint
        )

        bufferCanvas?.drawLine(
            selectItem.kLineX + (kLineWidth / 2) - 2f,
            framePadding,
            selectItem.kLineX + (kLineWidth / 2) - 2f,
            viewBottom,
            paint
        )

    }


}